package com.hibernate.db;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.junit.Test;

import com.hibernate.domain.Course;
import com.hibernate.domain.Student;
import com.hibernate.utils.HibernateUtils;

public class Many2ManyTest extends HibernateUtils {
	
	/**
	 * 保存学生的同时，级联保存课程
	 */
	@Test
	public void testSaveStudent_Cascade_SaveCourse() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Student student = new Student("张三","培训学生") ;
		Course course = new Course("1班", "培训班") ;
		Set<Course> courses = new HashSet<>() ;
		courses.add(course) ;
		//建立学生与课程的关系
		student.setCourses(courses) ;
		//保存学生的同时，级联保存课程
		session.save(student) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
	/**
	 * 保存课程的同时级联保存学生
	 */
	@Test
	public void testSaveCourse_Cascade_SaveStudent() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Course course = new Course("2班", "培训班") ;
		Student student01 = new Student("五五", "培训学生") ;
		Student student02 = new Student("六六", "培训学生") ;
		Set<Student> students = new HashSet<>() ;
		students.add(student01) ;
		students.add(student02) ;
		//建立课程与学生的关系
		course.setStudents(students) ;
		//保存课程，级联保存学生
		session.save(course) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
	
	/**
	 * 学生选多门课程
	 */
	@Test
	public void testBuildR() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Student student01 = (Student)session.get(Student.class, 1L) ;
		
		Course course1 = (Course)session.get(Course.class, 1L) ;
		Course course2 = (Course)session.get(Course.class, 2L) ;
		
		Set<Course> courses = new HashSet<>() ;
		courses.add(course1) ;
		courses.add(course2) ;
		//学生选课
		//方法一，先通过课程查询出学生，再添加学生，不推荐
//		course1.getStudents().add(student01) ;
		//方法二，学生关联课程
		student01.setCourses(courses) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
	/**
	 * 学生退选一门课程
	 */
	@Test
	public void testReleaseR() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Student student02 = (Student)session.get(Student.class, 2L) ;
		Course course2 = (Course)session.get(Course.class, 2L) ;
		//student02退选course2课程
		student02.getCourses().remove(course2) ;
		//或者：课程course2删除student02学生
//		course2.getStudents().remove(student02) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
	/**
	 * 学生退选多门课程
	 */
	@Test
	public void testRemoveSomeCourses_From_Student() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Student student = (Student)session.get(Student.class, 1L) ;
		Set<Course> courses = (Set<Course>) session.createQuery("from Course where cid in(1,2)").list() ;
		student.getCourses().removeAll(courses) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
	
	/**
	 * 取消课程：解除该课程和所有的学生之间的关联
	 */
	@Test
	public void testReleaseAllR() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Course course2 = (Course)session.get(Course.class, 2L) ;
		//解除该课程和所有的学生之间的关联
		course2.setStudents(null) ;
		
		transaction.commit() ;
		session.close() ;
	} 
	
	/**
	 * 学生调整课程：一个学生从一门课程转移到另外一门课程
	 */
	@Test
	public void testTransform() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
				
		Student student01 = (Student)session.get(Student.class, 1L) ;
		Course course1 = (Course)session.get(Course.class, 1L) ;
		Course course2 = (Course)session.get(Course.class, 2L) ;
		//取消课程course1
		student01.getCourses().remove(course1) ;
		//选择课程course2
		student01.getCourses().add(course2) ;
		
		transaction.commit() ;
		session.close() ;
	}
	
}
